import 'dart:convert';

import 'package:orginone/components/Tip/ToastUtils.dart';
import 'package:orginone/dart/base/model.dart';
import 'package:orginone/dart/base/schema.dart';
import 'package:orginone/dart/base/storages/hive_utils.dart';
import 'package:orginone/dart/base/storages/storage.dart';
import 'package:orginone/dart/core/public/consts.dart';
import 'package:orginone/main.dart';
import 'package:orginone/routers/pages.dart';
import 'package:orginone/routers/router_const.dart';
import 'package:orginone/utils/log/log_util.dart';

/// 授权方法提供者
class AuthProvider with AuthMixin {
  // 授权成功事件
  late Future<void> Function(XTarget user) _onAuthed;
  AuthProvider(Future<void> Function(XTarget user) authed) {
    _onAuthed = authed;
    tokenAuth();
  }

  Future<void> tokenAuth() async {
    String userjson = Storage.getString(Constants.sessionUser);
    if (tokenExpired()) {
      //token过期
    } else if (userjson.isNotEmpty) {
      kernel.user = XTarget.fromJson(jsonDecode(userjson));
      _onAuthed.call(kernel.user!);
    } else {
      kernel.tokenAuth().then((success) async {
        if (success && null != kernel.user) {
          Storage.setJson(Constants.sessionUser, kernel.user!.toJson());
          await _onAuthed.call(kernel.user!);
        }
      });
    }
  }

  /// 获取动态密码
  /// @param {RegisterType} params 参数
  Future<ResultType<DynamicCodeModel>> dynamicCode(
    DynamicCodeModel params,
  ) async {
    return await kernel.auth("DynamicPwd", params, DynamicCodeModel.fromJson);
  }

  /// 登录
  /// @param {RegisterType} params 参数
  Future<ResultType<TokenResultModel>> login(
    LoginModel params,
  ) async {
    var res = await kernel.auth<TokenResultModel>(
        'Login', params, TokenResultModel.fromJson);
    if (res.success) {
      await _onAuthed(res.data!.target);
    }
    return res;
  }

  /// 注册用户
  /// @param {RegisterType} params 参数
  Future<ResultType<TokenResultModel>> register(
    RegisterModel params,
  ) async {
    var res = await kernel.auth<TokenResultModel>(
        'Register', params, TokenResultModel.fromJson);
    if (res.success) {
      await _onAuthed(res.data!.target);
    }
    return res;
  }

  /// 变更密码
  /// @param account 账号
  /// @param password 密码
  /// @param privateKey 私钥
  /// @returns
  Future<ResultType<TokenResultModel>> resetPassword(
    ResetPwdModel params,
  ) async {
    var res = await kernel.auth<TokenResultModel>(
        'ResetPwd', params, TokenResultModel.fromJson);
    if (res.success) {
      await _onAuthed(res.data!.target);
    }
    return res;
  }
}

mixin AuthMixin {
  bool get loginStatus => Storage.getBool(Constants.loginStatus);

  String get initialRoute {
    String path = loginStatus
        ? relationCtrl.provider.inited
            ? Routers.home
            : Routers.logintrans
        : Routers.login;

    return path;
  }

  bool canAutoLogin([List<String>? account]) {
    account ??= Storage.getList(Constants.account);
    if (account.isNotEmpty && account.last != "") {
      return true;
    }
    return false;
  }

  void exitLogin([bool cleanUserLoginInfo = true]) async {
    kernel.stop();
    await HiveUtils.clean();
    Storage.remove(Constants.loginStatus);
    // Storage.remove(Constants.account);
    // Get.offAllNamed(Routers.login);
    RoutePages.to(path: Routers.login);
  }

  Future<void> refreshToken() async {
    var account = Storage.getList(Constants.account);
    if (!canAutoLogin(account)) {
      return exitLogin(false);
    }

    try {
      String accountName = account.first;
      String passWord = account.last;
      var res = await kernel.login(accountName, passWord);
      if (res.success) {
        XLogUtil.d("登陆成功Token:${kernel.accessToken}");
        // Get.offAndToNamed(Routers.logintrans, arguments: true);
        return;
      } else if (res.code == 401 || res.msg.contains('timeout')) {
        XLogUtil.d("登陆异常Token-401:${kernel.accessToken}");
        await refreshToken();
      } else {
        XLogUtil.d("登陆异常:${res.toJson()}");
        ToastUtils.showMsg(msg: res.msg);
        return exitLogin(false);
      }
    } catch (e) {
      XLogUtil.e(e);
    }
  }

  ///token是否过期
  bool tokenExpired() {
    int endTime = DateTime.now().millisecondsSinceEpoch;
    int startTime = Storage.getInt(Constants.appTokenGenerationTime);
    return endTime - startTime > 7000 * 1000;
  }
}
